package main

import "fmt"

// golang 函数中 return 不是原子操作 底层分为 两步 执行
// 1. 返回值赋值 (如果 没有 指定返回值 变量名 则为内部的一个 匿名变量)
// 2. 真正的 return 返回
// defer 执行的 时机是在 这两步之间
func demo() int {
	x := 5
	defer func() {
		// 此处修改的是 x 不是 真正的 返回值
		x++
	}()
	// 此时 x 已经赋值给返回值
	return x
}

func demo2() (x int) {
	defer func() {
		// 返回值 x++ = 6
		x++
	}()
	// 返回值 x 赋值为 5
	return 5
}

func demo3(index, a, b int) int {
	ret := a + b
	fmt.Printf("index: %d, a: %d, b: %d \t ret: %d\n", index, a, b, ret)
	return ret
}

func main() {
	res := demo()
	fmt.Printf("demo => %T %+v\n", res, res)

	res = demo2()
	fmt.Printf("demo => %T %+v\n", res, res)

	fmt.Println("=========================================================")

	// 1. defer demo3(1, a, demo3(4, a, b)) 先运算 里面的 demo3	a:1 b:2 ret:3 => defer demo3(1, 1, 3)
	// 2. a = 0
	// 3. defer demo3(2, a, demo3(3, a, b)) 先运算 里面的 demo3	a:0 b:2 ret:2 => defer demo3(2, 0, 2)
	// 4. b = 1
	// 5. defer demo3(2, a, demo3(3, a, b)) 此处 参数 demo3 已在第3步计算完毕 故为 defer demo3(2, 0, 2)	a:0 b:1 ret:2
	// 6. defer demo3(1, a, demo3(4, a, b)) 此处 参数 demo3 已在第1步计算完毕 故为 defer demo3(1, 1, 3)	a:0 b:1 ret:4
	a := 1
	b := 2
	defer demo3(1, a, demo3(4, a, b))
	a = 0
	defer demo3(2, a, demo3(3, a, b))
	b = 1
}
